objx("objx.list").requires("objx.class", "objx.property");

var OList = OClass({
	
	constraints: OProperty,
	items: OProperty,
	
	// constructor
	init: function(type){
	
		this._constraints = type ? OExtend({ isOClassType: type }, OList.defaultConstraints) : OList.defaultConstraints;
		this._items = [];
	
	},
	
	// Adds an item (or many items) to this list
	add: function(){
		
		if (arguments.length === 1) {
			
			var item = arguments[0];
			
			if (ODebug) {
				if (!OCheck(item, this._constraints)) {
					OError("objx.list", "The item you are trying to add (" + item + ") does not meet the specified constraints (" + this._constraints + ").");
				}
			}
			
			this._items.push(arguments[0]);
			
		} else {
			objx(arguments).each(function(argument){
				this.add(argument);
			}.bind(this));
		}
		
		return this;
	},
	
	insert: function(index) {
		
		if (ODebug) {
			if (arguments.length < 2) {
				OError("objx.list", "Cannot call OList.insert with " + arguments.length + " argument(s), must be at least 2.");
			}
		}
		
		if (arguments.length === 2) {
			
			var item = arguments[1];
			
			if (ODebug) {
				if (!OCheck(item, this._constraints)) {
					OError("objx.list", "The item you are trying to insert (" + item + ") does not meet the specified constraints (" + this._constraints + ").");
				}
			}
			
			this._items.splice(index, 0, item);
			
		} else {
			objx(arguments).each(true, function(argument, arg_index){
				if (arg_index == 0) return false;
				this.insert(index, argument);
			}.bind(this));
		}
		
		return this;
		
	},
	
	indexOf: function(i) {
		var foundIndex = -1;
		this.each(function(item, index){
			if (item === i) {
				foundIndex = index;
				return false;
			}
		});
		return foundIndex;
	},
	
	clear: function(){
		this._items.length = 0;
		return this;
	},
	
	removeAt: function(index) {
		this._items.splice(index, 1);
		return this;
	},
	
	remove: function(item) {
		var index = this.indexOf(item);
		if (index > -1) {
			this.removeAt(index);
		}
		return this;
	},
	
	item: function(index, newItem){
		if (typeof newItem === "undefined") {
			return this._items[index];
		} else {
			this._items[index] = newItem;
			return this;
		}
	},
	
	size: function(l){
		if (typeof l === "undefined") {
			return this._items.length;
		} else {
			this._items.length = l;
			return this;
		}
	},
	
	each: function(){
		var items = objx(this._items);
		items.each.apply(items, arguments);
		return this;
	}
	
});

// a set of constraints that all lists will have
OList.defaultConstraints = {};

OProvides("objx.list");